package sf.config;

//import com.alibaba.druid.pool.DruidDataSource;
//import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;

import com.zaxxer.hikari.HikariDataSource;
import org.smallframework.spring.DaoTemplate;
import org.smallframework.spring.mapper.DaoMapperScannerConfigurer;
import org.smallframework.springboot.SmallOrmAutoConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import sf.database.OrmConfig;
import sf.database.datasource.SimpleRoutingDataSource;
import sf.database.dialect.DialectUtils;
import sf.database.util.OrmValueUtils;
import sf.tools.StringUtils;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
// @EnableConfigurationProperties(GeeQueryConfigProperties.class)
public class DBConfig implements EnvironmentAware {
    private Environment env;

    public static final String SQL_TYPE_KEY = "sorm.test.sql.type";

    @Value("${" + SQL_TYPE_KEY + ":sqlite}")
    private String sqlType;

    @Override
    public void setEnvironment(Environment env) {
        this.env = env;
    }

//	@Bean(destroyMethod = "close", initMethod = "init")

    @Primary
    @Bean(name = "mysql")
    @ConfigurationProperties("spring.datasource.druid.one")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "mysql")
    public DataSource dataSourceMysql() {
//        DruidDataSource dds = DruidDataSourceBuilder.create().build();
//        return dds;
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }


    @Bean(name = "mysqlTransactionManager")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "mysql")
    public PlatformTransactionManager mysqlTransactionManager(@Qualifier("mysql") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "oracle")
    @ConfigurationProperties("spring.datasource.hikari.oracle")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "oracle")
    public DataSource dataSourceOracle() {
//		return DruidDataSourceBuilder.create().build();
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean(name = "sqlserver")
    @ConfigurationProperties("spring.datasource.hikari.sqlserver")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "sqlserver")
    public DataSource dataSourceSqlserver() {
//		return DruidDataSourceBuilder.create().build();
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean(name = "postgresql")
    @ConfigurationProperties("spring.datasource.druid.postgresql")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "postgresql")
    public DataSource dataSourcePostgresql() {
//        return DruidDataSourceBuilder.create().build();
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    //    @Primary
    @Bean(name = "sqlite")
    @ConfigurationProperties("spring.datasource.hikari.sqlite")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "sqlite")
    public DataSource dataSourceSqlite() {
//		return DruidDataSourceBuilder.create().build();
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    //    @Primary
//    @Bean(name = "sqliteTransactionManager")
    public PlatformTransactionManager sqliteTransactionManager(@Qualifier("sqlite") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

//    @Bean(name = "xaMysql")
//    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource")
//    @ConditionalOnProperty(name = sqlType, havingValue = "xaMysql")
//    public DataSource dataSourceJTAMyql() {
//        return new AtomikosDataSourceBean();
//    }

    @Bean(name = "h2")
    @ConfigurationProperties("spring.datasource.hikari.h2")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "h2")
    public DataSource dataSourceH2() {
//		return DruidDataSourceBuilder.create().build();
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean(name = "clickhouse")
    @ConfigurationProperties("spring.datasource.hikari.clickhouse")
    @ConditionalOnProperty(name = SQL_TYPE_KEY, havingValue = "clickhouse")
    public DataSource dataSourceClickhouse() {
//        DruidDataSource dds = DruidDataSourceBuilder.create().build();
//        return dds;
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }


    @Bean
    public OrmConfig getOrmConfig() {

//		DaoTemplate dt = new DaoTemplate(xaMysql);
        DialectUtils.lookDialect = (name, version) -> {
            if ("DM DBMS".equals(name)) {
                return new DMDialect();
            }
            return null;
        };
        OrmConfig config = OrmConfig.getInstance();
        config.setPackagesToScan(StringUtils.split("db.domain", ","));
        config.setUseTail(true);
        config.setBeanValueType(OrmValueUtils.BeanValueType.reflectasm);
        config.setUseSystemPrint(false);
        config.setShowCallChain(true);
        Map<String, String> paths = new HashMap<>();
        paths.put("freemarker", "classpath*:sql/**/freemarker*.*");
        paths.put("mybatis", "classpath*:sql/**/mybatis*.*");
        config.setSqlTemplatePaths(paths);
        return config;
    }

    @Bean(name = "daoTemplate")
    public DaoTemplate geDaoTemplate(@Autowired(required = false) @Qualifier("xaMysql") DataSource xaMysql,
                                     @Autowired(required = false) @Qualifier("mysql") DataSource mysql,
                                     @Autowired(required = false) @Qualifier("sqlite") DataSource sqlite,
                                     @Autowired(required = false) @Qualifier("h2") DataSource h2,
                                     @Autowired(required = false) @Qualifier("postgresql") DataSource postgresql,
                                     @Autowired(required = false) @Qualifier("oracle") DataSource oracle,
                                     @Autowired(required = false) @Qualifier("sqlserver") DataSource sqlserver,
                                     @Autowired(required = false) @Qualifier("clickhouse") DataSource clickhouse,
                                     OrmConfig ormConfig) {
        Map<String, DataSource> map = new HashMap<>();
        map.put("xaMysql", xaMysql);
        map.put("mysql", mysql);
        map.put("sqlite", sqlite);
        map.put("h2", h2);
        map.put("postgresql", postgresql);
        map.put("oracle", oracle);
        map.put("sqlserver", sqlserver);
        map.put("clickhouse", clickhouse);
        sqlType = env.getProperty(SQL_TYPE_KEY);
        DataSource ds = map.get(sqlType);
        SimpleRoutingDataSource routing = new SimpleRoutingDataSource(sqlType, ds, null);
//        routing.addDataSource("postgresql", postgresql);
        return SmallOrmAutoConfiguration.createDaoTemplate(routing, ormConfig,
                ormConfig.getPackagesToScan(), ormConfig.isInitScan());
    }

    @Bean
    public DaoMapperScannerConfigurer daoMapperScannerConfigurer() {
        DaoMapperScannerConfigurer dsc = new DaoMapperScannerConfigurer();
        dsc.setBasePackage("sf.mapper");
        dsc.setFactoryBeanName("daoTemplate");
        return dsc;
    }
    ///以下为jooq配置
}
